// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证（版本 2.0）进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动！任何基于本项目二次开发而产生的一切法律纠纷和责任，我们不承担任何责任！



using System.Data;

namespace MyDemo.Application;

/// <summary>
/// 学生服务
/// </summary>
[ApiDescriptionSettings(groups: ApplicationConst.GroupName, Order = 10)]
public class StudentService : IDynamicApiController, ITransient
{
    private readonly SqlSugarRepository<StudentEntity> _studentRep;
    private readonly IHttpContextAccessor _accessor;
    private readonly string user;

    public StudentService(
        SqlSugarRepository<StudentEntity> studentRep,
        IHttpContextAccessor accessor)
    {
        _studentRep = studentRep;

        _accessor = accessor;
        user = _accessor.HttpContext.Request.Headers["x-user"].GetCString();
    }

    /// <summary>
    /// 获取分页列表
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("获取分页列表")]
    public virtual async Task<SqlSugarPagedList<StudentEntity>> Page(PageStudentInput input)
    {

        Expression<Func<StudentEntity, bool>> whereExpression = whereExp =>
                   (input.StudentId.GetIsEmptyOrNull() || whereExp.StudentId.Equals(input.StudentId))
                   && (input.Name.GetIsEmptyOrNull() || whereExp.Name.ToLower().Contains(input.Name.ToLower().Trim()));
        return await _studentRep.AsQueryable()
            .WhereIF(whereExpression != null, whereExpression)
            .OrderBuilder(input)
            .ToPagedListAsync(input.Page, input.PageSize);
    }

    /// <summary>
    /// 获取列表
    /// </summary>
    /// <returns></returns>
    [DisplayName("获取列表")]
    public async Task<List<StudentEntity>> List(ListStudentInput input)
    {
        Expression<Func<StudentEntity, bool>> whereExpression = whereExp =>
                   (input.StudentId.GetIsEmptyOrNull() || whereExp.StudentId.Equals(input.StudentId))
                   && (input.Name.GetIsEmptyOrNull() || whereExp.Name.ToLower().Contains(input.Name.ToLower().Trim()))
               ;

        return await _studentRep.AsQueryable()
            .WhereIF(whereExpression != null, whereExpression)
            .ToListAsync();
    }

    /// <summary>
    /// 增加
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [UnitOfWork]
    [ApiDescriptionSettings(Name = "Add"), HttpPost]
    [DisplayName("增加")]
    public virtual async Task<int> Add(AddStudentInput input)
    {

        #region "校验唯一索引"

        Expression<Func<StudentEntity, bool>> whereExpression = whereExp =>
                    whereExp.School.Equals(input.School)
                    && whereExp.StudentId.Equals(input.StudentId)
               ;
        var data = await _studentRep.GetFirstAsync(whereExpression);
        if (data != null)
        {
            throw Oops.Oh(10001, "该记录已存在");
        }
        #endregion

        var insertEntity = input.Adapt<StudentEntity>();

        return await _studentRep.AsInsertable(insertEntity)
            .ExecuteCommandAsync();
    }

    /// <summary>
    /// 更新
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [UnitOfWork]
    [DisplayName("更新")]
    [ApiDescriptionSettings(Name = "Update"), HttpPut]
    public virtual async Task<int> Update(UpdateStudentInput input)
    {

        #region "校验唯一索引"
        Expression<Func<StudentEntity, bool>> whereExpression = whereExp =>
                    whereExp.Id.Equals(input.Id)
               ;
        var data = await _studentRep.GetFirstAsync(whereExpression);
        if (data == null)
        {
            throw Oops.Oh(10002, "该记录不存在");
        }
        #endregion

        var updateEntity = input.Adapt<StudentEntity>();
        return await _studentRep.AsUpdateable(updateEntity)
            .ExecuteCommandAsync();
    }

    /// <summary>
    /// 删除
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [UnitOfWork]
    [DisplayName("删除")]
    [ApiDescriptionSettings(Name = "Delete"), HttpDelete]  //可更改对外路由及Method类型
    public virtual async Task<int> Delete(DeleteStudentInput input)
    {
        #region "校验唯一索引"
        Expression<Func<StudentEntity, bool>> whereExpression = whereExp =>
                    whereExp.Id.Equals(input.Id)
               ;
        var data = await _studentRep.GetFirstAsync(whereExpression);
        if (data == null)
        {
            throw Oops.Oh(10002, "该记录不存在");
        }
        #endregion

        return await _studentRep.AsDeleteable()
            .ExecuteCommandAsync();
    }

    /// <summary>
    /// 批量删除
    /// </summary>
    /// <param name="inputList"></param>
    /// <returns></returns>
    [UnitOfWork]
    [ApiDescriptionSettings(Name = "BatchDelete"), HttpDelete]
    [DisplayName("批量删除")]
    public virtual async Task<int> BatchDeleteStudent(List<DeleteStudentInput> inputList)
    {
        #region "校验"
        foreach (var input in inputList)
        {
            Expression<Func<StudentEntity, bool>> whereExpression = whereExp =>
                        whereExp.Id.Equals(input.Id)
                   ;
            var data = await _studentRep.GetFirstAsync(whereExpression);
            if (data == null)
            {
                throw Oops.Oh(10002, "该记录不存在");
            }

            // *****校验是否有其他表使用该记录*****
        }
        #endregion

        return await _studentRep.AsDeleteable()
            .ExecuteCommandAsync();
    }

    /// <summary>
    /// 下载模版
    /// </summary>
    /// <returns></returns>
    [UnitOfWork]
    [DisplayName("下载模版")]
    public virtual async Task<IActionResult> DownloadTemplate()
    {
        #region "校验"
        string fileName = "studentTemplate.xlsx";
        string filePath = $"{AppDomain.CurrentDomain.BaseDirectory}/Template/{fileName}";
        if (!File.Exists(filePath))
        {
            throw Oops.Oh(10002, "找不到该模板：" + filePath);
        }
        #endregion

        var path = Path.Combine(filePath);
        return new FileStreamResult(new FileStream(path, FileMode.Open), System.Net.Mime.MediaTypeNames.Application.Octet)
        {
            FileDownloadName = fileName
        };
    }

    /// <summary>
    /// 导入
    /// </summary>
    /// <param name="file"></param>
    /// <returns></returns>
    [UnitOfWork]
    [DisplayName("导入")]
    public virtual async Task<List<ImportStudentOutput>> ImportStudent([Required] IFormFile file)
    {

        if (file != null)
        {
            var fileDir = AppDomain.CurrentDomain.BaseDirectory + @"ImportFile";
            if (!Directory.Exists(fileDir))
            {
                Directory.CreateDirectory(fileDir);
            }
            //文件名称
            string fileName = file.FileName;
            //文件类型
            string fileType = file.FileName.Substring(fileName.LastIndexOf("."));
            //上传的文件的路径
            string filePath = fileDir + $@"/{fileName}";
            if (File.Exists(filePath))
            {
                File.Delete(filePath);
            }
            using (FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite))
            {
                file.CopyTo(fs);
            }

            if (fileType == ".xlsx" || fileType == ".xls")
            {
                ExcelHelper eh = new ExcelHelper(filePath);
                DataTable dt = eh.ExcelToDataTable("", true);
                eh.Dispose();
                if (dt == null || dt.Rows.Count == 0)
                {
                    throw Oops.Oh(10002, "文件为空！");
                }

                #region "校验模板字段"
                if (!dt.Columns.Contains("学号") || !dt.Columns.Contains("姓名") || !dt.Columns.Contains("出生日期") || !dt.Columns.Contains("排序") || !dt.Columns.Contains("备注"))
                {
                    throw Oops.Oh(10003, "文件模板错误！请重新下载模板");
                }
                #endregion

                List<ImportStudentOutput> listLoad = new List<ImportStudentOutput>();
                foreach (DataRow row in dt.Rows)
                {
                    ImportStudentOutput importStudent = new ImportStudentOutput
                    {
                        #region "字段"
                        StudentId = row["学号"].GetCInt(),
                        Name = row["姓名"].GetCString(),
                        DateOfBirth = row["出生日期"].GetCDate(),
                        OrderNo = row["排序"].GetCInt(),
                        Remark = row["备注"].GetCString()
                        #endregion
                    };

                    #region "校验必填项"

                    #endregion

                    Expression<Func<StudentEntity, bool>> whereExpression = whereExp =>
                        whereExp.StudentId.Equals(importStudent.StudentId)
                    ;
                    var data = await _studentRep.GetFirstAsync(whereExpression);
                    if (data == null)
                    {
                        #region "自定义校验"

                        #endregion

                        var rtAdd = await _studentRep.AsInsertable(data).ExecuteCommandAsync();
                        if (rtAdd != 1)
                        {
                            importStudent.Code = 10001;
                            importStudent.Message = "插入失败";
                        }
                    }
                    else
                    {
                        #region "自定义校验"

                        #endregion

                        var rtUpdate = await _studentRep.AsUpdateable(data).ExecuteCommandAsync();
                        if (rtUpdate != 1)
                        {
                            importStudent.Code = 10001;
                            importStudent.Message = "更新失败";
                        }
                    }

                    if (importStudent.Code != 200)
                        listLoad.Add(importStudent);
                }

                // 返回导入失败数据
                if (listLoad.Count > 0)
                {
                    return listLoad;
                }
            }
            else
            {
                throw Oops.Oh(10002, "文件内容为空！");
            }
        }
        else
        {
            throw Oops.Oh(10002, "请选择文件！");
        }
        return null;
    }

    /// <summary>  
    /// 输出  
    /// </summary>  
    [UnitOfWork]
    [DisplayName("输出")]
    public virtual async Task<IActionResult> ExportStudent(ExportStudentInput input)
    {
        Expression<Func<StudentEntity, bool>> whereExpression = whereExp =>
                   (input.StudentId.GetIsEmptyOrNull() || whereExp.StudentId.Equals(input.StudentId))
                   && (input.Name.GetIsEmptyOrNull() || whereExp.Name.ToLower().Contains(input.Name.ToLower().Trim()));

        var dataTable = await _studentRep.AsQueryable()
            .WhereIF(whereExpression != null, whereExpression)
            .OrderBuilder(input)
            .ToDataTableAsync();

        #region 调整Excel字段输出顺序与前端一致  
        List<TableHeaderModel> listTableHeader = input.TableHead;
        if (listTableHeader == null || listTableHeader.Count == 0)
        {
            throw Oops.Oh(10002, "前端表格头信息错误");
        }

        DataTable dtHeader = dataTable.Clone();
        foreach (DataColumn col in dtHeader.Columns)
        {
            var tableColummn = listTableHeader.FirstOrDefault(p =>
                    ClassMapSqlsugar.GetDBColumnName<StudentEntity>(p.Property).ToLower() == col.ColumnName.ToLower()
                    && p.IsShow == true
                );
            if (listTableHeader != null && listTableHeader.Count > 0 && tableColummn != null)
            {
                dataTable.Columns[col.ColumnName].ColumnName = tableColummn.Label;
            }
            else
            {
                dataTable.Columns.Remove(col.ColumnName);
            }
        }
        int index = 0;
        if (dataTable.Columns.Count > 0)
            foreach (TableHeaderModel p in listTableHeader.Where(p => p.IsShow == true).ToList())
            {
                dataTable.Columns[p.Label].SetOrdinal(index);
                index++;
            }
        #endregion

        string path = AppDomain.CurrentDomain.BaseDirectory + "Export";
        if (!Directory.Exists(path))
        {
            Directory.CreateDirectory(path);
        }
        string fileName = $"StudentExport_{DateTime.Now.ToString("yyyyMMddHHmmss")}_{new Random().Next(10000000, 99999999)}.xlsx";
        string filePath = path + @"/" + fileName;
        ExcelHelper eh = new ExcelHelper(filePath);
        eh.DataTableToExcel(dataTable);

        return new FileStreamResult(new FileStream(filePath, FileMode.Open), System.Net.Mime.MediaTypeNames.Application.Octet)
        {
            FileDownloadName = fileName
        };




    }
}